﻿using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text.RegularExpressions;

namespace Neoit.Utils.TemplateParser
{
    /// <summary>
    /// common
    /// </summary>
    public class ParseCommon
    {
        public static bool IsDecimal(string str)
        {
            var pattern = $@"^-?\d+(.\d+)?$";
            if (str == null) return false;
            return Regex.IsMatch(str, pattern);
        }

        public static string TrimStart(string str, string trimStr)
        {
            if (str.StartsWith(trimStr))
            {
                return str[trimStr.Length..];
            }
            return str;
        }

        public static string JoinString<T>(IEnumerable<T> t, string separator = "")
        {
            if (t == null || !t.Any()) return null;
            return string.Join(separator, t);
        }
        public static object GetValueByPath(object obj, string path)
        {
            if (obj == null || string.IsNullOrEmpty(path))
            {
                return null;
            }
            #region decimal、string
            if (ParseCommon.IsDecimal(path))
            {
                return Convert.ToDecimal(path);
            }
            else if (Regex.IsMatch(path, @"^"".*""$"))
            {
                return path;
            }
            #endregion
            // Split path into parts by '.' but also consider possible list access indicated by [number]
            var parts = Regex.Split(path, @"(?<=\])\s*\.\s*|\.\s*");
            foreach (var part in parts)
            {
                if (obj == null) return null;

                // Check if the part contains indexing
                if (part.Contains("["))
                {
                    var propName = part.Substring(0, part.IndexOf("["));
                    var indexStr = part.Substring(part.IndexOf("[") + 1, part.IndexOf("]") - part.IndexOf("[") - 1);

                    if (int.TryParse(indexStr, out int index))
                    {
                        var list = obj.GetType().GetProperty(propName, BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Instance)?.GetValue(obj) as System.Collections.IList;

                        if (list != null && list.Count > index)
                        {
                            obj = list[index];
                        }
                        else
                        {
                            return null; // Index out of range
                        }
                    }
                    else
                    {
                        return null; // Invalid index
                    }
                }
                else
                {
                    if (obj is JObject jObject) {
                        obj = jObject[part]?.ToObject<object>();
                    }
                    else
                    {
                        var propertyInfo = obj.GetType().GetProperty(part, BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Instance);
                        obj = propertyInfo?.GetValue(obj);
                    }
                }
            }
            return obj;
        }

        internal static string AdjustLabelLine(string template, string startTagPattern, string endTagPattern)
        {
            var regex = new Regex($"{startTagPattern}|{endTagPattern}", RegexOptions.Singleline);
            var matches = regex.Matches(template);
            template = Regex.Replace(template, $"\r\n *?({startTagPattern}|{endTagPattern}) *?\r\n", "\r\n$1", RegexOptions.Singleline);
            if (Regex.IsMatch(template, $"\r\n *?({startTagPattern}|{endTagPattern}) *?\r\n"))
            {
                return AdjustLabelLine(template, startTagPattern, endTagPattern);
            }
            return template;
        }
    }
}
